﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace UniversityPhoneCrawler
{
    public partial class MainForm : Form
    {
        private readonly HttpClient _httpClient;
        private readonly ConcurrentDictionary<string, List<string>> _phoneUrls;
        private ConcurrentBag<string> _visitedUrls = new ConcurrentBag<string>();

        private int _maxThreads = 5; // 控制并发数
        private SemaphoreSlim _throttler;

        public MainForm()
        {
            InitializeComponent();
            _httpClient = new HttpClient();
            _httpClient.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0");
            _phoneUrls = new ConcurrentDictionary<string, List<string>>();
            _visitedUrls = new ConcurrentBag<string>();
            _throttler = new SemaphoreSlim(_maxThreads);
        }

        private async void btnSearch_Click(object sender, EventArgs e)
        {
            string keyword = txtKeyword.Text.Trim();
            if (string.IsNullOrEmpty(keyword))
            {
                MessageBox.Show("请输入搜索关键词");
                return;
            }

            // 重置状态
            _phoneUrls.Clear();
            _visitedUrls = new ConcurrentBag<string>();
            lstResults.Items.Clear();
            progressBar1.Value = 0;
            lblStatus.Text = "开始搜索...";

            try
            {
                await StartCrawling(keyword);
                lblStatus.Text = $"完成！找到 {_phoneUrls.Count} 个高校电话";
            }
            catch (Exception ex)
            {
                lblStatus.Text = $"错误: {ex.Message}";
            }
        }

        private async Task StartCrawling(string keyword)
        {
            // 使用搜索引擎获取初始URL
            var searchUrls = await GetSearchResults(keyword);

            // 创建任务列表
            var tasks = new List<Task>();
            foreach (var url in searchUrls)
            {
                tasks.Add(ProcessUrl(url));
            }

            await Task.WhenAll(tasks);

            // 显示结果
            DisplayResults();
        }

        private async Task<List<string>> GetSearchResults(string keyword)
        {
            // 模拟从搜索引擎获取结果（实际应用中需要替换为真实搜索引擎API）
            // 这里仅作演示，返回一些常见高校网站
            return new List<string>
            {
                "https://www.tsinghua.edu.cn",
                "https://www.pku.edu.cn",
                "https://www.fudan.edu.cn",
                "https://www.zju.edu.cn",
                "https://www.sjtu.edu.cn",
                "https://www.nju.edu.cn",
                "https://www.ustc.edu.cn",
                "https://www.ruc.edu.cn",
                "https://www.tongji.edu.cn",
                "https://www.whu.edu.cn"
            };
        }

        private async Task ProcessUrl(string url)
        {
            await _throttler.WaitAsync();
            try
            {
                if (_visitedUrls.Contains(url)) return;
                _visitedUrls.Add(url);

                Invoke((Action)(() => lstUrls.Items.Add(url)));

                string html = await FetchHtml(url);
                if (string.IsNullOrEmpty(html)) return;

                // 提取电话号码
                ExtractPhoneNumbers(html, url);

                // 提取页面中的其他链接继续爬取
                var links = ExtractLinks(html);
                foreach (var link in links)
                {
                    if (!_visitedUrls.Contains(link) && IsUniversityUrl(link))
                    {
                        await ProcessUrl(link);
                    }
                }
            }
            finally
            {
                _throttler.Release();
                UpdateProgress();
            }
        }

        private async Task<string> FetchHtml(string url)
        {
            try
            {
                // 添加延迟防止被封
                await Task.Delay(1000);
                return await _httpClient.GetStringAsync(url);
            }
            catch
            {
                return null;
            }
        }

        private void ExtractPhoneNumbers(string html, string url)
        {
            // 高校电话正则表达式（匹配常见格式）
            string pattern = @"(?:电话|联系方式)[：:\s]*([0-9]{3,4}-[0-9]{7,8}|[0-9]{7,8})";
            var matches = Regex.Matches(html, pattern);

            foreach (Match match in matches)
            {
                if (match.Groups.Count > 1)
                {
                    string phone = match.Groups[1].Value;
                    _phoneUrls.AddOrUpdate(phone,
                        new List<string> { url },
                        (key, list) => { list.Add(url); return list; });
                }

                // 找到100个就停止
                if (_phoneUrls.Count >= 100) break;
            }
        }

        private List<string> ExtractLinks(string html)
        {
            var links = new List<string>();
            string pattern = @"href\s*=\s*[""']?([^'"" >]+)[""']?";
            var matches = Regex.Matches(html, pattern);

            foreach (Match match in matches)
            {
                if (match.Groups.Count > 1)
                {
                    links.Add(match.Groups[1].Value);
                }
            }

            return links;
        }

        private bool IsUniversityUrl(string url)
        {
            // 简单判断是否是高校网站
            return url.Contains(".edu.cn") || url.Contains("大学") || url.Contains("学院");
        }

        private void DisplayResults()
        {
            lstResults.BeginUpdate();
            lstResults.Items.Clear();

            foreach (var pair in _phoneUrls)
            {
                string item = $"{pair.Key} (来自: {string.Join(", ", pair.Value)})";
                lstResults.Items.Add(item);
            }

            lstResults.EndUpdate();
        }

        private void UpdateProgress()
        {
            Invoke((Action)(() =>
            {
                int progress = (int)((double)_visitedUrls.Count / 100 * 100);
                progressBar1.Value = Math.Min(progress, 100);
                lblStatus.Text = $"已爬取 {_visitedUrls.Count} 个页面，找到 {_phoneUrls.Count} 个电话";
            }));
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            if (_phoneUrls.Count == 0)
            {
                MessageBox.Show("没有可保存的数据");
                return;
            }

            SaveFileDialog saveFileDialog = new SaveFileDialog
            {
                Filter = "文本文件|*.txt",
                Title = "保存电话号码"
            };

            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                using (System.IO.StreamWriter file =
                    new System.IO.StreamWriter(saveFileDialog.FileName))
                {
                    foreach (var pair in _phoneUrls)
                    {
                        file.WriteLine($"{pair.Key}\t{string.Join(",", pair.Value)}");
                    }
                }
                MessageBox.Show("保存成功！");
            }
        }
    }
}